namespace Brjnk.GpxExplorer.Data.GPX
{
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using Brjnk.Common;
    using Brjnk.GpxExplorer.Data.GPX.SerializationClasses;

    /// <summary>
    /// </summary>
    public class GpxWaypoint : Waypoint, IGpxObject
    {
        private wptType data;

        public GpxWaypoint(wptType data)
        {
            this.data = data;
            if (data.extensions != null && data.extensions.geocache != null)
                geocache = new GpxGeocache(data.extensions.geocache);
        }

        public GpxWaypoint()
            : this(new wptType())
        {
        }

        public object GetUnderlayingObject()
        {
            if (geocache != null)
            {
                if (data.extensions == null) data.extensions = new waypointExtensionsType();
                if (geocache is GpxGeocache)
                {
                    data.extensions.geocache = (cache)(geocache as GpxGeocache).GetUnderlayingObject();
                }
                else
                {
                    data.extensions.geocache = (cache)geocache.ConvertTo<GpxGeocache>().GetUnderlayingObject();
                }
            }
            else
            {
                if (data.extensions != null) data.extensions.geocache = null;
            }
            return data;
        }

        public override Common.GpsCoordinates Position
        {
            get
            {
                return new Common.GpsCoordinates((double)data.lat, (double)data.lon);
            }
            set
            {
                data.lat = (decimal)value.LatTotalDegree;
                data.lon = (decimal)value.LonTotalDegree;
                OnPropertyChanged("Position");
            }
        }

        public override string Name
        {
            get
            {
                return data.name;
            }
            set
            {
                data.name = value;
                OnPropertyChanged("Name");
            }
        }

        public override string Comment
        {
            get
            {
                return data.cmt;
            }
            set
            {
                data.cmt = value;
                OnPropertyChanged("Comment");
            }
        }

        public override DateTime? Time
        {
            get
            {
                if (data.timeSpecified == false) return null;
                return data.time.ToLocalTime();
            }
            set
            {
                if (value.HasValue)
                {
                    data.time = value.Value.ToUniversalTime();
                    data.timeSpecified = true;
                }
                else
                {
                    data.time = default(DateTime).ToUniversalTime();
                    data.timeSpecified = false;
                }
                OnPropertyChanged("Time");
            }
        }

        public override Distance? Elevation
        {
            get
            {
                if (data.eleSpecified == false) return null;
                return (double)data.ele;
            }
            set
            {
                if (value.HasValue)
                {
                    data.ele = (decimal)(double)value.Value;
                    data.eleSpecified = true;
                }
                else
                {
                    data.ele = default(decimal);
                    data.eleSpecified = false;
                }
                OnPropertyChanged("Elevation");
            }
        }

        public override Link Link
        {
            get
            {
                if (data.link == null || data.link.Count == 0) return null;
                return new Link(data.link.First().text, data.link.First().href);
            }
            set
            {
                if (value == null) data.link = null;
                else
                {
                    linkType l = new linkType();
                    l.href = value.Url;
                    l.text = value.Text;
                    if (data.link == null) data.link = new List<linkType>();
                    if (data.link.Count == 0) data.link.Add(l);
                    else data.link[0] = l;
                }
                OnPropertyChanged("Link");
            }
        }

        public override string Description
        {
            get
            {
                return data.desc;
            }
            set
            {
                data.desc = value;
                OnPropertyChanged("Description");
            }
        }

        private GeocacheInfo geocache;

        public override GeocacheInfo Geocache
        {
            get
            {
                return geocache;
            }
            set
            {
                geocache = value;
                OnPropertyChanged("Geocache");
            }
        }

        public override WaypointSymbol? Symbol
        {
            get
            {
                if (string.IsNullOrEmpty(data.sym)) return null;
                return Converter.StringToSymbol(data.sym);
            }
            set
            {
                if (value.HasValue)
                {
                    data.sym = Converter.SymbolToString(value.Value);
                }
                else
                {
                    data.sym = null;
                }
                OnPropertyChanged("Symbol");
            }
        }
    }
}